package gui;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.naming.directory.InvalidAttributesException;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

import model.Process;
import model.ProductType;
import service.Service;

/**
 * 
 * @author Ceslovas Lopan
 * 
 */
public class AddEditType extends JFrame {
	private final Controller controller = new Controller();
	private Component owner;
	private JTextField txfProductName;
	private JList lstSelectedProcesses, lstAllProcesses;
	private JButton btnAddProcess, btnRemoveProcess, btnSave, btnCancel;
	private DefaultListModel dlmSelected, dlmAll;
	private ProductType productType = null;

	public AddEditType(Component owner, ProductType pt) {
		this(owner);
		this.productType = pt;

		fillData();
	}

	public AddEditType(Component owner) {
		this.owner = owner;
		setSize(567, 461);
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		setLocation(100, 100);
		setResizable(false);
		setTitle("Add/Edit ProductType");
		getContentPane().setLayout(new BorderLayout(0, 0));

		JPanel panel = new JPanel();
		FlowLayout flowLayout = (FlowLayout) panel.getLayout();
		flowLayout.setAlignment(FlowLayout.LEFT);
		getContentPane().add(panel, BorderLayout.NORTH);

		JLabel lblName = new JLabel("Name");
		panel.add(lblName);

		txfProductName = new JTextField();
		panel.add(txfProductName);
		txfProductName.setColumns(10);

		JPanel panel1 = new JPanel();
		getContentPane().add(panel1, BorderLayout.WEST);
		panel1.setLayout(new GridLayout(10, 1, 0, 0));

		btnAddProcess = new JButton("Add process");
		panel1.add(btnAddProcess);

		btnRemoveProcess = new JButton("Remove process");
		panel1.add(btnRemoveProcess);

		JPanel panel2 = new JPanel();
		FlowLayout flowLayout1 = (FlowLayout) panel2.getLayout();
		flowLayout1.setAlignment(FlowLayout.RIGHT);
		getContentPane().add(panel2, BorderLayout.SOUTH);

		btnSave = new JButton("Save");
		panel2.add(btnSave);

		btnCancel = new JButton("Cancel");
		panel2.add(btnCancel);

		JPanel panel3 = new JPanel();
		getContentPane().add(panel3, BorderLayout.CENTER);
		panel3.setLayout(new GridLayout(0, 2, 5, 0));

		JPanel panel4 = new JPanel();
		panel3.add(panel4);
		panel4.setLayout(new BorderLayout(0, 0));

		JPanel panel7 = new JPanel();
		panel4.add(panel7, BorderLayout.NORTH);

		JLabel lblProductProcesses = new JLabel("Product processes");
		panel7.add(lblProductProcesses);

		JScrollPane scrollPane = new JScrollPane();
		panel4.add(scrollPane, BorderLayout.CENTER);

		dlmSelected = new DefaultListModel();

		lstSelectedProcesses = new JList(dlmSelected);
		scrollPane.setViewportView(lstSelectedProcesses);

		JPanel panel5 = new JPanel();
		panel3.add(panel5);
		panel5.setLayout(new BorderLayout(0, 0));

		JPanel panel6 = new JPanel();
		FlowLayout flowLayout2 = (FlowLayout) panel6.getLayout();
		flowLayout2.setAlignment(FlowLayout.LEFT);
		panel5.add(panel6, BorderLayout.NORTH);

		JLabel lblAvailableProcesses = new JLabel("Available processes");
		panel6.add(lblAvailableProcesses);

		JScrollPane scrollPane1 = new JScrollPane();
		panel5.add(scrollPane1, BorderLayout.CENTER);

		dlmAll = new DefaultListModel();

		for (Process p : Service.getInstance().getProcesses()) {
			dlmAll.addElement(p);
		}

		lstAllProcesses = new JList(dlmAll);
		scrollPane1.setViewportView(lstAllProcesses);

		btnAddProcess.addActionListener(controller);
		btnRemoveProcess.addActionListener(controller);
		btnSave.addActionListener(controller);
		btnCancel.addActionListener(controller);
	}

	public void fillData() {
		if (productType == null)
			return;

		txfProductName.setText(productType.getName());

		for (Process p : productType.getRecipe()) {
			dlmSelected.addElement(p);
		}

		for (Process p : Service.getInstance().getProcesses()) {
			if (dlmSelected.contains(p))
				dlmAll.removeElement(p);
		}
	}

	private class Controller implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent e) {
			if (e.getSource() == btnAddProcess) {
				Object sel = lstAllProcesses.getSelectedValue();

				if (sel != null) {
					dlmAll.removeElement(sel);
					dlmSelected.addElement(sel);
				}
			} else if (e.getSource() == btnRemoveProcess) {
				int index = lstSelectedProcesses.getSelectedIndex();

				if (index >= 0) {
					dlmAll.addElement(dlmSelected.get(index));
					dlmSelected.remove(index);
				}
			} else if (e.getSource() == btnSave) {
				String name = txfProductName.getText();
				List<Object> procsObjects = new ArrayList<Object>(
						Arrays.asList(dlmSelected.toArray()));

				if (procsObjects.size() > 0) {
					Process[] p = new Process[procsObjects.size()];
					procsObjects.toArray(p);

					ArrayList<Process> processes = new ArrayList<Process>(
							Arrays.asList(p));

					ProductType result = null;

					try {
						if (productType == null) {
							result = Service.getInstance().addProductType(name,
									processes);
						} else {
							result = Service.getInstance().editProductType(
									productType, name, processes);
						}
					} catch (InvalidAttributesException ex) {
						JOptionPane.showMessageDialog(AddEditType.this,
								"Product type cannot contain same processes",
								"Error", JOptionPane.ERROR_MESSAGE);
					}

					if (result != null) {
						AddEditType.this.dispose();
					} else {
						JOptionPane.showMessageDialog(AddEditType.this,
								"Type could not be created", "Error",
								JOptionPane.ERROR_MESSAGE);
					}
					if (owner instanceof ManageData) {
						((ManageData) owner).updateLists();
					}
				} else {
					JOptionPane.showMessageDialog(AddEditType.this,
							"Type should contain at least one process",
							"Error", JOptionPane.ERROR_MESSAGE);
				}
			} else if (e.getSource() == btnCancel) {
				AddEditType.this.dispose();
			}
		}
	}
}
